home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p2.arc / SCHED.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  19.9 KB  |  756 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software <no-Inc>                   */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          No-Cost<no-tm> Software.                       */
  7. /*        \ 1011 /                                                          */
  8. /*         ------            KopyRong (K) 1987.  ALL RIGHTS REVERSED.       */
  9. /*                                                                          */
  10. /*                                                                          */
  11. /*                 This module was written by Bob Hartman                   */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                     BinkleyTerm Scheduler Routines                       */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*   This  software  package is being distributed WITH FULL SOURCE CODE     */
  18. /*   with the  following  conditions:    1)  If  anything awful happens     */
  19. /*   because  you  use    it   (or  don't  use  it),  you  accept  full     */
  20. /*   responsibility;  2) you  don't start making tons of voice calls to     */
  21. /*   the authors to complain or  make  suggestions  about enhancements,     */
  22. /*   useful or otherwise;  3) you  do not reuse this code in commercial     */
  23. /*   products without specific permission to do so  from  the  authors;     */
  24. /*   4) If you find any problems you send  fixes  to  the  authors  for     */
  25. /*   inclusion  in  updates;    5) You find some way  to  express  your     */
  26. /*   appreciation  for  this  method of distribution, either by writing     */
  27. /*   code or  application  notes,  or  just sending along a "Thank You"     */
  28. /*   message.                                                               */
  29. /*                                                                          */
  30. /*   There is  copyrighted  code  in  this product.  We either wrote it     */
  31. /*   ourselves or got  permission  to use it.  Please don't force us to     */
  32. /*   pay a lawyer --  have some respect for our motives and don't abuse     */
  33. /*   this "license".                                                        */
  34. /*                                                                          */
  35. /*                                                                          */
  36. /*--------------------------------------------------------------------------*/
  37.  
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <sys/utime.h>
  43. #include "sched.h"
  44.  
  45. extern char *skip_blanks();
  46. extern char *BINKpath;
  47.  
  48. EVENT *e_ptrs[256];
  49. int num_events = 0;
  50. int cur_event = -1;
  51. int got_sched = 0;
  52. int noforce = 0;
  53. int max_connects = 3;
  54. int max_noconnects = 10000;
  55.  
  56. extern char no_requests;
  57. extern char *skip_blanks();
  58.  
  59. char *skip_to_blank (string)
  60. char *string;
  61. {
  62.    while (*string && (!isspace (*string)))
  63.       ++string;
  64.    return (string);
  65. }
  66.  
  67. char *start_time (e, p)
  68. EVENT *e;
  69. char *p;
  70. {
  71.    int i, j;
  72.  
  73.    if (sscanf (p, "%d:%d", &i, &j) != 2)
  74.       {
  75.       return NULL;
  76.       }
  77.  
  78.    e->minute = i*60+j;
  79.    if ((e->minute < 0) || (e->minute > (24*60)))
  80.       {
  81.       return (NULL);
  82.       }
  83.  
  84.    p = skip_to_blank (p);
  85.  
  86.    return (p);
  87. }
  88.  
  89. char *end_time (e, p)
  90. EVENT *e;
  91. char *p;
  92. {
  93.    int i, j, k;
  94.  
  95.    if (sscanf (p, "%d:%d", &i, &j) != 2)
  96.       {
  97.       return NULL;
  98.       }
  99.  
  100.    k = i*60+j;
  101.    if ((k > (24*60)) || (k < 0))
  102.       {
  103.       return (NULL);
  104.       }
  105.  
  106.    if (k < e->minute)
  107.       {
  108.       printf ("Ending time wraps through midnight - not allowed\n");
  109.       return (NULL);
  110.       }
  111.  
  112.    e->length = k - e->minute;
  113.  
  114.    p = skip_to_blank (p);
  115.  
  116.    return (p);
  117. }
  118.  
  119. parse_event (e_line)
  120. char *e_line;
  121. {
  122.    int i, j, j1, j2;
  123.    char *p, *p1;
  124.    EVENT *e;
  125.  
  126.    /* If we already have a schedule, then forget it */
  127.    if (got_sched)
  128.       return (0);
  129.  
  130.    /* Skip blanks to get to the days field */
  131.    p = skip_blanks(e_line);
  132.  
  133.    /* Parse the days field */
  134.    e = (EVENT *) calloc (sizeof (EVENT), 1);
  135.    e->days = 0;
  136.    e->wait_time = 120;
  137.    while ((*p) && (!isspace(*p)))
  138.       {
  139.       switch (toupper(*p))
  140.          {
  141.          case 'S':   /* Sunday or Saturday */
  142.             if (!strnicmp (p, "sun", 3))
  143.                {
  144.                e->days |= DAY_SUNDAY;
  145.                }
  146.             else if (!strnicmp (p, "sat", 3))
  147.                {
  148.                e->days |= DAY_SATURDAY;
  149.                }
  150.             else  /* Error condition */
  151.                {
  152.                goto err;
  153.                }
  154.             p += 3;
  155.             break;
  156.  
  157.          case 'M':   /* Monday */
  158.             if (!strnicmp (p, "mon", 3))
  159.                {
  160.                e->days |= DAY_MONDAY;
  161.                }
  162.             else  /* Error condition */
  163.                {
  164.                goto err;
  165.                }
  166.             p += 3;
  167.             break;
  168.  
  169.          case 'T':   /* Tuesday or Thursday */
  170.             if (!strnicmp (p, "tue", 3))
  171.                {
  172.                e->days |= DAY_TUESDAY;
  173.                }
  174.             else if (!strnicmp (p, "thu", 3))
  175.                {
  176.                e->days |= DAY_THURSDAY;
  177.                }
  178.             else  /* Error condition */
  179.                {
  180.                goto err;
  181.                }
  182.             p += 3;
  183.             break;
  184.  
  185.          case 'W':   /* Wednesday, Week or Weekend */
  186.             if (!strnicmp (p, "wed", 3))
  187.                {
  188.                e->days |= DAY_WEDNESDAY;
  189.                p += 3;
  190.                }
  191.             else if (!strnicmp (p, "week", 4))
  192.                {
  193.                e->days |= DAY_WEEK;
  194.                p += 4;
  195.                }
  196.             else if (!strnicmp (p, "wkend", 5))
  197.                {
  198.                e->days |= DAY_WKEND;
  199.                p += 5;
  200.                }
  201.             else  /* Error condition */
  202.                {
  203.                goto err;
  204.                }
  205.             break;
  206.  
  207.          case 'F':   /* Friday */
  208.             if (!strnicmp (p, "fri", 3))
  209.                {
  210.                e->days |= DAY_FRIDAY;
  211.                }
  212.             else  /* Error condition */
  213.                {
  214.                goto err;
  215.                }
  216.             p += 3;
  217.             break;
  218.  
  219.          case 'A':   /* All */
  220.             if (!strnicmp (p, "all", 3))
  221.                {
  222.                e->days |= (DAY_WEEK|DAY_WKEND);
  223.                }
  224.             else  /* Error condition */
  225.                {
  226.                goto err;
  227.                }
  228.             p += 3;
  229.             break;
  230.  
  231.          default:    /* Error condition */
  232.             goto err;
  233.          }
  234.  
  235.       if (*p == '|')
  236.          ++p;
  237.       }
  238.  
  239.    /* Did we get something valid? */
  240.    if (e->days == 0)
  241.       {
  242.       goto err;
  243.       }
  244.  
  245.    /* Skip blanks to get to the start-time field */
  246.    p = skip_blanks (p);
  247.  
  248.    /* Parse the start-time field */
  249.    if ((p = start_time (e, p)) == NULL)
  250.       {
  251.       printf ("'%s' has an invalid START-TIME\n", e_line);
  252.       free (e);
  253.       return (1);
  254.       }
  255.  
  256.    /* Give each event a default of 60 minutes */
  257.    e->length = 60;
  258.  
  259.    /* While there are still things on the line */
  260.    while (*p)
  261.       {
  262.       /* Skip blanks to get to the next field */
  263.       p = skip_blanks (p);
  264.  
  265.       /* switch to find what thing is being parsed */
  266.       switch (tolower(*p))
  267.          {
  268.          case '\0':  /* No more stuff */
  269.             break;
  270.          
  271.          case '0':   /* Digits must be an ending time */
  272.          case '1':
  273.          case '2':
  274.          case '3':
  275.          case '4':
  276.          case '5':
  277.          case '6':
  278.          case '7':
  279.          case '8':
  280.          case '9':
  281.             /* Parse ending time */
  282.             if ((p = end_time (e, p)) == NULL)
  283.                {
  284.                printf ("'%s' has an invalid END-TIME\n", e_line);
  285.                free (e);
  286.                return (1);
  287.                }
  288.             break;
  289.  
  290.          case ';':   /* Comment */
  291.          case '%':
  292.             *p = '\0';
  293.             break;
  294.  
  295.          case 'a':   /* Average wait */
  296.             ++p;
  297.             if (*p == '=')
  298.                {
  299.                ++p;
  300.                if (isdigit (*p))
  301.                   {
  302.                   i = atoi (p);
  303.                   if ((i > 240) || (i < 0))
  304.                      {
  305.                      printf ("'%s' has bad AvgWait (higher than max of 240 or less than min of 0)\n", e_line);
  306.                      free (e);
  307.                      return (1);
  308.                      }
  309.                   e->wait_time = i;
  310.                   p = skip_to_blank (p);
  311.                   break;
  312.                   }
  313.                }
  314.             printf ("'%s' has a bad AvgWait code\n", e_line);
  315.             free (e);
  316.             return (1);
  317.  
  318.          case 'b':   /* BBS type event */
  319.             p = skip_to_blank (p);
  320.             e->behavior |= MAT_BBS;
  321.             break;
  322.  
  323.          case 'c':   /* #CM event */
  324.             p = skip_to_blank (p);
  325.             e->behavior |= MAT_CM;
  326.             break;
  327.  
  328.          case 'd':   /* Dynamic event */
  329.             p = skip_to_blank (p);
  330.             e->behavior |= MAT_DYNAM;
  331.             break;
  332.  
  333.          case 'e':   /* An errorlevel exit */
  334.             ++p;
  335.             if (isdigit(*p))
  336.                {
  337.                i = *p - '0';
  338.                ++p;
  339.                if ((*p == '=') && (i <= 5) && (i > 0))
  340.                   {
  341.                   ++p;
  342.                   if (isdigit (*p))
  343.                      {
  344.                      j = atoi (p);
  345.                      e->errlevel[i-1] = j;
  346.                      p = skip_to_blank (p);
  347.                      break;
  348.                      }
  349.                   }
  350.                }
  351.             printf ("'%s' has a bad Errorlevel code\n", e_line);
  352.             free (e);
  353.             return (1);
  354.  
  355.          case 'f':   /* Forced event */
  356.             p = skip_to_blank (p);
  357.             e->behavior |= MAT_FORCED;
  358.             break;
  359.  
  360.          case 'l':   /* Local only mail */
  361.             p = skip_to_blank (p);
  362.             e->behavior |= MAT_LOCAL;
  363.             break;
  364.  
  365.          case 'n':   /* No requests */
  366.             p = skip_to_blank (p);
  367.             e->behavior |= MAT_NOREQ;
  368.             break;
  369.  
  370.          case 'r':   /* Receive only */
  371.             p = skip_to_blank (p);
  372.             e->behavior |= MAT_NOOUT;
  373.             break;
  374.  
  375.          case 's':   /* Send only */
  376.             p = skip_to_blank (p);
  377.             e->behavior |= MAT_OUTONLY;
  378.             break;
  379.  
  380.          case 't':   /* Tries */
  381.             ++p;
  382.             if (sscanf (p, "=%d,%d", &j1, &j2) != 2)
  383.                {
  384.                printf ("'%s' has a bad number of Tries\n", e_line);
  385.                return (1);
  386.                }
  387.             else
  388.                {
  389.                if ((j1 > 8) || (j1 < 1))
  390.                   {
  391.                   printf ("'%s' has a bad number of Tries\n", e_line);
  392.                   return (1);
  393.                   }
  394.                max_connects = j1;
  395.                max_noconnects = j2;
  396.                }
  397.             p = skip_to_blank (p);
  398.             break;
  399.  
  400.          default:    /* Error condition */
  401.             printf ("'%s' has something indecipherable\n", e_line);
  402.             free (e);
  403.             return (1);
  404.          }
  405.       }
  406.  
  407.    /* Save it in the array  of pointers */
  408.    e_ptrs[num_events++] = e;
  409.  
  410. /*
  411. printf ("\nEvent shows:\n");
  412. printf ("  days = %04x\n", e->days);
  413. printf ("  minute = %d\n", e->minute);
  414. printf ("  length = %d\n", e->length);
  415. for (i = 0; i < 5; i++)
  416. printf ("  err[%d] = %d\n", i, e->errlevel[i]);
  417. */
  418.  
  419.    /* Return that everything is cool */
  420.    return (0);
  421.  
  422. err:
  423.    printf ("'%s' has an invalid DAY field\n", e_line);
  424.    free (e);
  425.    return (1);
  426. }
  427.  
  428. find_event ()
  429. {
  430.    int cur_day;
  431.    int cur_hour;
  432.    int cur_minute;
  433.    int cur_mday;
  434.    int cur_mon;
  435.    int cur_year;
  436.    int junk, junk1;
  437.    int our_time;
  438.    int i;
  439.    int j;
  440.  
  441.    /* Get the current time in minutes */
  442.    dostime (&cur_hour, &cur_minute, &junk, &junk);
  443.    our_time = cur_hour * 60 + cur_minute;
  444.  
  445.    /* Get the current day of the week */
  446.    dosdate (&cur_mon, &cur_mday, &cur_year, &cur_day);
  447.  
  448.    /* Make the month 0 based */
  449.    --cur_mon;
  450.  
  451.    cur_day = 1 << cur_day;
  452.  
  453.    cur_event = -1;
  454.  
  455.    /* Go through the events from top to bottom */
  456.    for (i = 0; i < num_events; i++)
  457.       {
  458.       if (our_time >= e_ptrs[i]->minute)
  459.          {
  460.          if (cur_day & e_ptrs[i]->days)
  461.             {
  462.             if (((our_time-e_ptrs[i]->minute) < e_ptrs[i]->length) ||
  463.                 ((our_time == e_ptrs[i]->minute) && (e_ptrs[i]->length == 0)) ||
  464.                 ((e_ptrs[i]->behavior & MAT_FORCED) && (e_ptrs[i]->last_ran != cur_mday)))
  465.                {
  466.                /* Are we not supposed to force old events */
  467.                if (((our_time-e_ptrs[i]->minute) > e_ptrs[i]->length) && (noforce))
  468.                   {
  469.                   e_ptrs[i]->last_ran = cur_mday;
  470.                   continue;
  471.                   }
  472.  
  473.                if (e_ptrs[i]->last_ran != cur_mday)
  474.                   {
  475.                   set_xy("");
  476.                   status_line (":Starting Event %d", i + 1);
  477.  
  478.                   /* Mark that this one is running */
  479.                   e_ptrs[i]->last_ran = cur_mday;
  480.  
  481.                   /* Write out the schedule */
  482.                   write_sched();
  483.  
  484.                   /* If we are supposed to exit, then do it */
  485.                   if (e_ptrs[i]->errlevel[0])
  486.                      {
  487.                      status_line("#Exit at start of event with errorlevel %d",
  488.                                    e_ptrs[i]->errlevel[0]);
  489.  
  490.                      errl_exit (e_ptrs[i]->errlevel[0]);
  491.                      }
  492.                   }
  493.                else
  494.                   {
  495.                   /* Don't do events that have been exited already */
  496.                   if (e_ptrs[i]->behavior & MAT_SKIP)
  497.                      continue;
  498.                   }
  499.  
  500.                cur_event = i;
  501.  
  502.                if (e_ptrs[i]->behavior & MAT_NOREQ)
  503.                   no_requests = 1;
  504.                else
  505.                   no_requests = 0;
  506.  
  507.                break;
  508.                }
  509.             }
  510.          }
  511.       }
  512.  
  513. /*
  514. printf("\nCurrent event is event %d\n", cur_event);
  515. if (cur_event >= 0)
  516. {
  517. printf ("Event shows:\n");
  518. printf ("  days = %04x\n", e_ptrs[cur_event]->days);
  519. printf ("  minute = %d\n", e_ptrs[cur_event]->minute);
  520. printf ("  length = %d\n", e_ptrs[cur_event]->length);
  521. for (i = 0; i < 5; i++)
  522. printf ("  err[%d] = %d\n", i, e_ptrs[cur_event]->errlevel[i]);
  523. }
  524. */
  525. }
  526.  
  527. read_sched ()
  528. {
  529.    char temp1[80], temp2[80];
  530.    char *malloc();
  531.    EVENT *sptr;
  532.    struct stat buffer1, buffer2;
  533.    FILE *f;
  534.    int i;
  535.  
  536.    strcpy(temp1,BINKpath);
  537.    strcpy(temp2,BINKpath);
  538.    strcat(temp1,"Binkley.Scd");
  539.    strcat(temp2,"Binkley.Cfg");
  540.  
  541.    if (stat (temp1, &buffer1))
  542.       {
  543.       return;
  544.       }
  545.  
  546.    if (stat (temp2, &buffer2))
  547.       {
  548.       return;
  549.       }
  550.  
  551.    if ((buffer1.st_atime < buffer2.st_atime) ||
  552.        (buffer1.st_size < sizeof(EVENT)))
  553.       {
  554.       return;
  555.       }
  556.  
  557.    if ((sptr = (EVENT *) malloc ((int) buffer1.st_size)) == NULL)
  558.       {
  559.       return;
  560.       }
  561.  
  562.    if ((f = fopen (temp1, "rb")) == NULL)
  563.       {
  564.       return;
  565.       }
  566.  
  567.    fread (sptr, (int) buffer1.st_size, 1, f);
  568.    got_sched = 1;
  569.  
  570.    num_events = buffer1.st_size / sizeof (EVENT);
  571.    for (i = 0; i < num_events; i++)
  572.       {
  573.       e_ptrs[i] = sptr++;
  574.       }
  575.  
  576.    fclose (f);
  577.    return;
  578. }
  579.  
  580. write_sched ()
  581. {
  582.    char temp1[80], temp2[80];
  583.    FILE *f;
  584.    int i;
  585.    struct stat buffer1;
  586.    struct utimbuf times;
  587.    long t;
  588.    extern long time();
  589.  
  590.    /* Get the current time */
  591.    t = time (NULL);
  592.  
  593.    strcpy(temp1,BINKpath);
  594.    strcpy(temp2,BINKpath);
  595.    strcat(temp1,"Binkley.Scd");
  596.    strcat(temp2,"Binkley.Cfg");
  597.  
  598.    /* Get the current stat for .Cfg file */
  599.    if (!stat (temp2, &buffer1))
  600.       {
  601.       /* If it is newer than current time, we have a problem and
  602.          we must reset the file date - yucky, but it will probably work */
  603.       if (t < buffer1.st_atime)
  604.          {
  605.          times.actime = buffer1.st_atime;
  606.          times.modtime = buffer1.st_atime;
  607.          status_line ("!Date rollover problem?");
  608.          }
  609.       else
  610.          {
  611.          times.actime = t;
  612.          times.modtime = t;
  613.          }
  614.       }
  615.  
  616.    if ((f = fopen (temp1, "wb")) == NULL)
  617.       {
  618.       return;
  619.       }
  620.  
  621.    for (i = 0; i < num_events; i++)
  622.       {
  623.       /* If it is skipped, but not dynamic, reset it */
  624.       if ((e_ptrs[i]->behavior & MAT_SKIP) &&
  625.           (!(e_ptrs[i]->behavior & MAT_DYNAM)))
  626.          {
  627.          e_ptrs[i]->behavior &= ~MAT_SKIP;
  628.          }
  629.  
  630.       /* Write this one out */
  631.       fwrite (e_ptrs[i], sizeof (EVENT), 1, f);
  632.       }
  633.  
  634.    fclose (f);
  635.  
  636.    utime (temp1, ×);
  637.  
  638.    return;
  639. }
  640.  
  641. time_to_next ()
  642. {
  643.    int cur_day;
  644.    int cur_hour;
  645.    int cur_minute;
  646.    int cur_mday;
  647.    int cur_mon;
  648.    int cur_year;
  649.    int junk, junk1;
  650.    int our_time;
  651.    int i;
  652.    int time_to;
  653.    int guess;
  654.    int nmin;
  655.  
  656.    /* Get the current time in minutes */
  657.    dostime (&cur_hour, &cur_minute, &junk, &junk);
  658.    our_time = cur_hour * 60 + cur_minute;
  659.  
  660.    /* Get the current day of the week */
  661.    dosdate (&cur_mon, &cur_mday, &cur_year, &cur_day);
  662.  
  663.    /* Make the month 0 based */
  664.    --cur_mon;
  665.  
  666.    cur_day = 1 << cur_day;
  667.  
  668.    /* A ridiculous number */
  669.    time_to = 3000;
  670.  
  671.    /* Go through the events from top to bottom */
  672.    for (i = 0; i < num_events; i++)
  673.       {
  674.       /* If it is the current event, skip it */
  675.       if (cur_event == i)
  676.          continue;
  677.  
  678.       /* If it is a BBS event, skip it */
  679.       if (e_ptrs[i]->behavior & MAT_BBS)
  680.          continue;
  681.  
  682.       /* If it was already run today, skip it */
  683.       if (e_ptrs[i]->last_ran == cur_mday)
  684.          continue;
  685.  
  686.       /* If it doesn't happen today, skip it */
  687.       if (!(e_ptrs[i]->days & cur_day))
  688.          continue;
  689.  
  690.       /* If it is earlier than now, skip it unless it is forced */
  691.       if (e_ptrs[i]->minute < our_time)
  692.          {
  693.          if (!(e_ptrs[i]->behavior & MAT_FORCED))
  694.             {
  695.             continue;
  696.             }
  697.  
  698.          /* Hmm, found a forced event that has not executed yet */
  699.          /* Give the guy 2 minutes and call it quits */
  700.          guess = 2;
  701.          }
  702.       else
  703.          {
  704.          /* Calculate how far it is from now */
  705.          guess = e_ptrs[i]->minute - our_time;
  706.          }   
  707.  
  708.       /* If less than closest so far, keep it */
  709.       if (time_to > guess)
  710.          time_to = guess;
  711.       }
  712.  
  713.    /* If we still have nothing, then do it again, starting at midnight */
  714.    if (time_to >= 1441)
  715.       {
  716.       /* Calculate here to midnight */
  717.       nmin = 1440 - our_time;
  718.  
  719.       /* Go to midnight */
  720.       our_time = 0;
  721.  
  722.       /* Go to the next possible day */
  723.       cur_day = cur_day << 1;
  724.       if (cur_day > DAY_SATURDAY)
  725.          cur_day = DAY_SUNDAY;
  726.  
  727.       /* Go through the events from top to bottom */
  728.       for (i = 0; i < num_events; i++)
  729.          {
  730.          /* If it is a BBS event, skip it */
  731.          if (e_ptrs[i]->behavior & MAT_BBS)
  732.             continue;
  733.  
  734.          /* If it doesn't happen today, skip it */
  735.          if (!(e_ptrs[i]->days & cur_day))
  736.             continue;
  737.  
  738.          /* Calculate how far it is from now */
  739.          guess = e_ptrs[i]->minute + nmin;
  740.  
  741.          /* If less than closest so far, keep it */
  742.          if (time_to > guess)
  743.             time_to = guess;
  744.          }
  745.       }
  746.  
  747.    if (time_to > 1440)
  748.       time_to = 1440;
  749.  
  750.    if (time_to < 1)
  751.       time_to = 1;
  752.  
  753.    return (time_to);
  754. }
  755.  
  756.